#ifndef _EDBROOT_H_
#define _EDBROOT_H_

#define EDBROOT_FOREACH_CHILD(sr, child)		\
	for (child = edbroot_first(sr); child; child = edbroot_next_free(child))

#define EDBROOT_FOREACH_CHILD_N(sr, child, next)	\
	for (child = edbroot_first(sr), next = edbroot_next(child); child; tree_unlock(child, PIN_LOCK), child = next, next = edbroot_next(child))

#define EDBROOT_FOREACH_CHILD_NF(sr, child, next)	\
	for (child = edbroot_first_lock(sr, PIN_LOCK), next = edbroot_next_lock(child, PIN_LOCK); child; tree_unlock(child, PIN_LOCK), child = next, next = edbroot_next_lock(child, PIN_LOCK))

#define EDBROOT_FOREACH_CHILD_RETURN(sr_child, res)	\
	do { tree_unlock(sr_child, PIN_LOCK); return (res); } while (0)

#define EDBROOT_FOREACH_CHILD_NF_RETURN(sr_child, sr_next_child, res)	\
	do { tree_unlock(sr_child, PIN_LOCK); tree_unlock(sr_next_child, PIN_LOCK); return (res); } while (0)

sr_t *edbroot_get_root(void);
char *edbroot_get_LNP(const sr_t *sr);
ECMBOOL edbroot_is_ontree(const sr_t *sr);
ECM_INLINE sr_t *edbroot_get_parent(const sr_t *sr);
ECM_INLINE sr_t *edbroot_first(const sr_t *sr);
ECM_INLINE sr_t *edbroot_last(const sr_t *sr);
ECM_INLINE sr_t *edbroot_next(const sr_t *sr);
ECM_INLINE sr_t *edbroot_prev(const sr_t *sr);
ECM_INLINE sr_t *edbroot_next_free(const sr_t *sr);
ECM_INLINE sr_t *edbroot_first_lock(const sr_t *sr, treelock_t type);
ECM_INLINE sr_t *edbroot_next_lock(const sr_t *sr, treelock_t type);
ECM_INLINE sr_t *edbroot_next_lock_free(const sr_t *sr, treelock_t type);
sr_t *edbroot_dup(const sr_t *sr_src);
ECMBOOL edbroot_exist(const sr_t *sr_dir, const char *name);

edb_err_t edbroot_set_val(edbd_conn_t edbd_conn, sr_t *sr, sr_val_t val, ECMBOOL logging);
edb_err_t edbroot_set_asrv(edbd_conn_t edbd_conn, sr_t *sr, const char *asrv, ECMBOOL logging);
edb_err_t edbroot_clear_val(edbd_conn_t edbd_conn, sr_t *sr, ECMBOOL logging);
edb_err_t edbroot_get_val(edbd_conn_t conn, sr_t *sr, sr_val_t *pval);

sr_t *edbroot_get(const sr_t *sr_anchor, const sr_t *sr_LNP);
sr_t *edbroot_getn(const sr_t *sr_anchor, const char *LNP);
sr_t *edbroot_getc(const sr_t *sr_group, const char *name);

sr_t *edbroot_get_from_cwd(edbd_conn_t conn, const sr_t *sr_LNP);

edb_err_t edbroot_del(edbd_conn_t conn, sr_t *sr, ECMBOOL logging, ECMBOOL force);

edb_err_t edbroot_apply_owner(edbd_conn_t edbd_conn, sr_t *sr, xid_t owner);
edb_err_t edbroot_set_owner(edbd_conn_t edbd_conn, sr_t *sr, xid_t owner);
edb_err_t edbroot_set_user(edbd_conn_t edbd_conn, sr_t *sr, const char *username);
edb_err_t edbroot_set_group(edbd_conn_t edbd_conn, sr_t *sr, const char *grpname);
edb_err_t edbroot_set_perm(edbd_conn_t edbd_conn, sr_t *sr, eds_perm_t perm);
edb_err_t edbroot_set_attr_update(edbd_conn_t edbd_conn, sr_t *sr, ecm_uint32 attr_update);
edb_err_t edbroot_set_attr_fetch(edbd_conn_t edbd_conn, sr_t *sr, ecm_uint32 attr_fetch);
edb_err_t edbroot_append(edbd_conn_t conn, sr_t *sr_dir, sr_t *sr, ECMBOOL logging);
edb_err_t edbroot_set_reactors(edbd_conn_t edbd_conn, sr_t *sr, sr_t *sr_edexprs);
ECMBOOL edbroot_start_reactors(edbd_conn_t edbd_conn, sr_t *sr);
ECMBOOL edbroot_stop_reactors(edbd_conn_t edbd_conn, sr_t *sr);

ECM_INLINE ECMBOOL edbroot_empty(const sr_t *sr);
void edbroot_invalidate_subtree(sr_t *sr); 
void edbroot_free(sr_t *sr);
void edbroot_release(sr_t *sr, ECMBOOL from_get);

sr_t *edbroot_dup_ref(const sr_t *sr_ref);
sr_t *edbroot_get_deref(const sr_t *sr_ref);
edb_err_t edbroot_set_ref(edbd_conn_t edbd_conn, sr_t *sr, sr_t *sr_LNP, ECMBOOL logging);
edb_err_t edbroot_set_target(edbd_conn_t edbd_conn, sr_t *sr, const sr_t *sr_target, ECMBOOL logging);

sr_t *edbroot_xecreate(edbd_conn_t conn, sr_t *sr_HMS, const char *name, srt_t srt, xid_t creator_xid, ECMBOOL logging);
edb_err_t edbroot_xedelete(edbd_conn_t conn, sr_t *sr_xe, ECMBOOL logging, ECMBOOL force);
sr_t *edbroot_xeappend(edbd_conn_t conn, sr_t *sr_HMS, sr_t *sr_xe, xid_t creator_xid, ECMBOOL logging);

int edbroot_get_num_child(const sr_t *sr_group);

char *edbroot_build_xe_name(const sr_t *sr_HMS, const char *c_name);

void edbroot_invalidate_ref(edbd_conn_t edbd_conn, sr_t *sr);
void edbroot_setup_ref(void);
void edbroot_unsetup_ref(void);

ECMBOOL edbroot_start(edbd_conn_t edbd_conn);
void edbroot_stop(edbd_conn_t edbd_conn);

#endif
